package com.cts.learninglibrary.config.shiro;

import com.cts.learninglibrary.config.shiro.server.LoginFilter;
import com.cts.learninglibrary.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import java.util.HashMap;
import java.util.Map;

/**
 * @author arctique
 * @date 2020/8/24 9:20
 */
@Configuration
@Slf4j
public class ShiroConfig {

    private final int HAS_URL = 1;

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.password}")
    private String password;

    @Autowired
    private RedisUtil redisUtil;

    @Bean("shiroFilterFactoryBean")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {

        log.info("[shiro拦截器工厂开启]");

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        LoginFilter loginFilter = new LoginFilter();
        loginFilter.setRedisTemplateService(redisUtil);

        // 设置安全管理
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.getFilters().put("login", loginFilter);

        // 设置踢出登录和无权跳转
        shiroFilterFactoryBean.setLoginUrl("/notLogin");
        shiroFilterFactoryBean.setUnauthorizedUrl("/noAccess");

        Map<String, String> filterChainDefinitionMap = new HashMap<>();

        // 开放登录接口
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/userInfo", "anon");

        filterChainDefinitionMap.put("/noAccess", "anon");
        filterChainDefinitionMap.put("/notLogin", "anon");
        // 获取权限
//        List<Permission> permissionList = permissionService.findByHasUrl(HAS_URL);
//        if (CollectionUtils.isEmpty(permissionList)) {
//            return null;
//        }
//        for (Permission permission : permissionList) {
//            if (permission.getParentId() != 0) {
//                filterChainDefinitionMap.put(permission.getUrl(),
//                        "perms[" + permission.getCode() + "],login");
//            }
//            log.info("[初始化权限] : {}", permission.getCode());
//        }
//
<<<<<<< HEAD
        //暂时关闭shiro拦截
//        filterChainDefinitionMap.put("/**", "authc");
        filterChainDefinitionMap.put("/**", "anon");
=======
        filterChainDefinitionMap.put("/share/**", "authc");
>>>>>>> 69e9e286e8a1653af821beff2f1680538e5b913d
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        log.info("[shiro拦截器工厂加载完毕]");
        return shiroFilterFactoryBean;
    }

    @Bean("securityManager")
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //设置Realm
        securityManager.setRealm(userRealm());
        securityManager.setSessionManager(sessionManager());
        securityManager.setCacheManager(cacheManager());
        return securityManager;
    }

    @Bean("userRealm")
    public UserRealm userRealm() {
        UserRealm userRealm = new UserRealm();
        userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return userRealm;
    }

    @Bean("hashedCredentialsMatcher")
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        hashedCredentialsMatcher.setHashIterations(1);
        return hashedCredentialsMatcher;
    }

    @Bean("sessionManager")
    public StatelessSessionManagerConfig sessionManager() {
        StatelessSessionManagerConfig mySessionManager = new StatelessSessionManagerConfig();
        mySessionManager.setSessionDAO(redisSessionDao());
        return mySessionManager;
    }

    @Bean("redisSessionDao")
    public SessionDAO redisSessionDao() {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        return redisSessionDAO;
    }

    @Bean("cacheManager")
    public RedisCacheManager cacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        return redisCacheManager;
    }

    @Bean("redisManager")
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(host);
        redisManager.setPort(port);
        // 配置缓存过期时间
        redisManager.setExpire(3600);
        redisManager.setTimeout(0);
        redisManager.setPassword(password);
        return redisManager;
    }

    @Bean("authorizationAttributeSourceAdvisor")
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    @Bean("lifecycleBeanPostProcessor")
    public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
}
